﻿using System;
using Kugar.Core.BaseStruct;

namespace Kugar.Tool.Web.RequestFieldValidation.Rules
{
    public class ComparableValueRule<TInputValue>: RuleBase
        where TInputValue : IComparable
    {
        internal ComparableValueRule(TInputValue compareValue, CompareOpt opt,string errorMsg):base(errorMsg)
        {
            CompareValue = compareValue;
            Opt = opt;
        }

        public TInputValue CompareValue { get; }
        

        public CompareOpt Opt { get; }

        protected override string BuildDefaultErrorMessage(IRequestField field)
        {
            return Localizer[$"{0}必须{optToStr(Opt)}{1}", field.Title, CompareValue];// $"{field.Title}必须{optToStr(Opt)}{CompareValue}";
        }

        //public ResultReturn Validate(IRequestField field)
        //{
        //    var f = (IRequestField<TInputValue>) field;

        //    var result = CompareValue.CompareTo(f.Value());
        //    var isSuccess = false;

        //    switch (Opt)
        //    {
        //        case CompareOpt.GT:
        //            isSuccess = result > 0;
        //            break;
        //        case CompareOpt.GTE:
        //            isSuccess = result >= 0;
        //            break;
        //        case CompareOpt.LT:
        //            isSuccess = result < 0;
        //            break;
        //        case CompareOpt.LTE:
        //            isSuccess = result >= 0;
        //            break;
        //        case CompareOpt.EQ:
        //            isSuccess = result == 0;
        //            break;
        //        default:
        //            throw new ArgumentOutOfRangeException();
        //    }

        //    if (isSuccess)
        //    {
        //        return SuccessResultReturn.Default;
        //    }
        //    else
        //    {
        //        return new FailResultReturn($"{field.Title}{optToStr(Opt)}{CompareValue}");
        //    }
        //}

        //protected override string BuildErrorMessage(IRequestField field)
        //{
        //    var tmp = (IRequestField<TInputValue>) field;

        //    return $"{tmp.Title}{optToStr(Opt)}{CompareValue}";
        //}

        protected override bool ValidateField(IRequestField field)
        {
            var f = (IRequestField<TInputValue>) field;

            var value = f.Value();

            if (value == null)
            {
                return true;
            }

            var result = f.Value().CompareTo(CompareValue);
            var isSuccess = false;

            switch (Opt)
            {
                case CompareOpt.GT:
                    isSuccess = result > 0;
                    break;
                case CompareOpt.GTE:
                    isSuccess = result >= 0;
                    break;
                case CompareOpt.LT:
                    isSuccess = result < 0;
                    break;
                case CompareOpt.LTE:
                    isSuccess = result <= 0;
                    break;
                case CompareOpt.EQ:
                    isSuccess = result == 0;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return isSuccess;
        }

        private string optToStr(CompareOpt opt)
        {
            switch (opt)
            {
                case CompareOpt.GT:
                    return "大于";
                case CompareOpt.GTE:
                    return "大于等于";
                case CompareOpt.LT:
                    return "小于";
                case CompareOpt.LTE:
                    return "小于等于";
                case CompareOpt.EQ:
                    return "等于";
                default:
                    throw new ArgumentOutOfRangeException(nameof(opt), opt, null);
            }
        }
        
    }

    public class ComparableValueRuleNullable<TInputValue> : RuleBase
    where TInputValue : struct 
    {
        internal ComparableValueRuleNullable(TInputValue? compareValue, CompareOpt opt, string errorMsg) : base(errorMsg)
        {
            CompareValue = compareValue;
            Opt = opt;
        }

        public TInputValue? CompareValue { get; }


        public CompareOpt Opt { get; }

        protected override string BuildDefaultErrorMessage(IRequestField field)
        {
            return Localizer["{0}必须" + optToStr(Opt) + "{1}",field.Title,CompareValue];//$"{field.Title}必须{optToStr(Opt)}{CompareValue}";
        }

        //public ResultReturn Validate(IRequestField field)
        //{
        //    var f = (IRequestField<TInputValue>) field;

        //    var result = CompareValue.CompareTo(f.Value());
        //    var isSuccess = false;

        //    switch (Opt)
        //    {
        //        case CompareOpt.GT:
        //            isSuccess = result > 0;
        //            break;
        //        case CompareOpt.GTE:
        //            isSuccess = result >= 0;
        //            break;
        //        case CompareOpt.LT:
        //            isSuccess = result < 0;
        //            break;
        //        case CompareOpt.LTE:
        //            isSuccess = result >= 0;
        //            break;
        //        case CompareOpt.EQ:
        //            isSuccess = result == 0;
        //            break;
        //        default:
        //            throw new ArgumentOutOfRangeException();
        //    }

        //    if (isSuccess)
        //    {
        //        return SuccessResultReturn.Default;
        //    }
        //    else
        //    {
        //        return new FailResultReturn($"{field.Title}{optToStr(Opt)}{CompareValue}");
        //    }
        //}

        //protected override string BuildErrorMessage(IRequestField field)
        //{
        //    var tmp = (IRequestField<TInputValue>) field;

        //    return $"{tmp.Title}{optToStr(Opt)}{CompareValue}";
        //}

        protected override bool ValidateField(IRequestField field)
        {
            var f = (IRequestField<TInputValue?>)field;

            var value = f.Value();

            if (value == null)
            {
                return true;
            }


            var result = Nullable.Compare(f.Value(), CompareValue);
            var isSuccess = false;

            switch (Opt)
            {
                case CompareOpt.GT:
                    isSuccess = result > 0;
                    break;
                case CompareOpt.GTE:
                    isSuccess = result >= 0;
                    break;
                case CompareOpt.LT:
                    isSuccess = result < 0;
                    break;
                case CompareOpt.LTE:
                    isSuccess = result <= 0;
                    break;
                case CompareOpt.EQ:
                    isSuccess = result == 0;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return isSuccess;
        }

        private string optToStr(CompareOpt opt)
        {
            switch (opt)
            {
                case CompareOpt.GT:
                    return "大于";
                case CompareOpt.GTE:
                    return "大于等于";
                case CompareOpt.LT:
                    return "小于";
                case CompareOpt.LTE:
                    return "小于等于";
                case CompareOpt.EQ:
                    return "等于";
                default:
                    throw new ArgumentOutOfRangeException(nameof(opt), opt, null);
            }
        }

    }

    public enum CompareOpt
    {
        GT,

        GTE,

        LT,

        LTE,

        EQ,
    }
}